using UnityEngine;
using System.Collections;

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

public class LC_WWW {
	public enum HTTPMETHOD{
		GET,
		POST,
		PUT,
		DELETE
	}
	
	private string _text;
	private string _error;
	private bool isDone;
	private int _status = 200;
	
	private string _flashText;
	private string _flashError;
	private bool flashIsDone;
//	private int _flashStatus = 200;

	private string url;
	private string path;
	
	private Hashtable _parameter = new Hashtable();
	private Hashtable _requestHeader = new Hashtable();
	private Hashtable _responseHeader = new Hashtable();
	private byte[] _image;
	private HTTPMETHOD method = HTTPMETHOD.GET;
	
	private TcpClient client;

	public string text 
	{
		get { return _text; }
	}
	public string error
	{
		get { return _error; }
	}
	public int Status
	{
		get { return _status; } 
		set { _status = value; }	//for Debug.
	}
	public bool IsDone
	{
		get{ return isDone; }
	}
	public Hashtable Parameters 
	{
		get { return _parameter; }
		set { _parameter = value; }
	}
	public Hashtable RequestHeaders
	{
		get { return _requestHeader; }
		set { _requestHeader = value; }
	}
	public Hashtable ResponseHeaders 
	{
		get { return _responseHeader; }
		set { _responseHeader = value; }
	}
	public HTTPMETHOD Method
	{
		get { return method; }
		set { method = value; }
	}
	
	public byte[] image
	{
		get { return _image; }
		set { _image = value; }
	}
	
	public LC_WWW(string url)
	{
		if(url.Contains("://")){
			Debug.Log("This class support https.(https://yourdomain.com, yourdomain.com)");
		}
		
		if(url.IndexOf("/") != -1){
			this.url = url.Substring(0,url.IndexOf("/"));
			this.path = url.Substring(url.IndexOf("/"));
			
			if(path == ""){
				this.path = "/index.html";
			}
		}
		else{
			this.url = url;
			this.path = "/index.html";
		}
	}
	~LC_WWW(){
		if(client.Connected){
			Debug.Log("call calll call call! " + path);
			client.Close();
		}
		else{
			Debug.Log("no connect Call");
		}
	}

	ThreadStart ts;
	Thread mThread;
	
	public void Send()
	{
		ts = new ThreadStart(SendPacket);
		mThread = new Thread(ts);
        mThread.Start();	
	}
	
	public void SendPhoto()
	{
		ts = new ThreadStart(SendMultipartPacket);
		mThread = new Thread(ts);
        mThread.Start();
	}

	void SendPacket()
	{
		isDone = false;

		client = new TcpClient(this.url, 8080);
		
		Debug.Log("LC_WWW : SendPacket : Client connected.");
		
		NetworkStream networkStream = client.GetStream();
		
		System.Text.UTF8Encoding  encoding=new System.Text.UTF8Encoding();
		
		int i=0;
		string tempParam = null;
		byte[] arr = null;	
		if(_parameter.Count != 0){
			foreach(string key in _parameter.Keys){
				if(i==0){
					tempParam += key+"="+_parameter[key].ToString();
				}
				else{
					tempParam += "&"+key+"="+_parameter[key].ToString();
				}
				i++;
			}
			arr = encoding.GetBytes(tempParam);
		}
		if(method == HTTPMETHOD.GET){
			if(_parameter.Count != 0){
				this.path = this.path + "?"+ tempParam;
			}
		}
		try
		{
			Debug.Log("url : " + this.url);
			Debug.Log("path : " + this.path);
			
			byte[] messsage = Encoding.UTF8.GetBytes(method.ToString() + " " + this.path+" HTTP/1.1\r\n");
				
	        networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Host: "+ this.url +"\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ko; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
//			messsage = Encoding.UTF8.GetBytes("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
//			networkStream.Write(messsage, 0, messsage.Length);
//			messsage = Encoding.UTF8.GetBytes("Accept-Language: ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3\r\n");
//			networkStream.Write(messsage, 0, messsage.Length);
//			messsage = Encoding.UTF8.GetBytes("Accept-Encoding: gzip,deflate\r\n");
//			networkStream.Write(messsage, 0, messsage.Length);
//			messsage = Encoding.UTF8.GetBytes("Accept-Charset: EUC-KR,utf-8;q=0.7,*;q=0.7\r\n");
//			networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Keep-Alive: 115\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Connection: keep-alive\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			Debug.LogError(method.ToString());
			
			if(_requestHeader.Count != 0){
				foreach(string key in _requestHeader.Keys){
					Debug.Log(key + " : " + _requestHeader[key].ToString());
					messsage = Encoding.UTF8.GetBytes(key + ": " + _requestHeader[key].ToString()  +"\r\n");
					networkStream.Write(messsage, 0, messsage.Length);
				}
			}

            if(method != HTTPMETHOD.GET && arr != null){
				messsage = Encoding.UTF8.GetBytes("Content-Type: application/x-www-form-urlencoded\r\n");
				networkStream.Write(messsage, 0, messsage.Length);
				messsage = Encoding.UTF8.GetBytes("Content-Length: " + arr.Length +"\r\n");
				networkStream.Write(messsage, 0, messsage.Length);
			}

            messsage = Encoding.UTF8.GetBytes("\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			
			if(method != HTTPMETHOD.GET && arr != null){
				networkStream.Write(arr, 0, arr.Length);
			}
	        networkStream.Flush();
	        // Read message from the server.
	        string serverMessage = ReadMessage(networkStream);
	        Debug.Log("Server says: "+ serverMessage);
			
			_text = MakeHeader(serverMessage).Trim().Replace("\n","");
	        // Close the client connection.
	        client.Close();
	        Debug.Log("Client closed.");
		}
		catch (Exception e){
			_error += e.Message;
			Debug.Log(e.Message);
		}
		
		isDone = true;
	}
/*
	IEnumerator SendPacket()
	{
		isDone = false;
		Debug.Log("LC_WWW : SendPacket : Client connected.");
		
		WWWForm form = new WWWForm();
		Hashtable tempHeader = form.headers;
		System.Text.UTF8Encoding  encoding=new System.Text.UTF8Encoding();
		
		foreach(string key in _requestHeader.Keys)
			tempHeader.Add(key, _requestHeader[key].ToString());
		
		_parameter.Add("api", this.apis);
		_parameter.Add("method", method.ToString().ToLower());
		
		int i=0;
		string tempParam = null;
		byte[] arr = null;	
		if(_parameter.Count != 0){
			foreach(string key in _parameter.Keys){
				if(i==0){
					tempParam += key+"="+_parameter[key].ToString();
				}
				else{
					tempParam += "&"+key+"="+_parameter[key].ToString();
				}
				i++;
			}
			arr = encoding.GetBytes(tempParam);
		}
 				
//		Debug.Log("url : " + this.url);
//		Debug.Log("RealURL : beta.rest.bumpingbear.com/proxy");
		
		WWW www = new WWW("beta.rest.bumpingbear.com/proxy/rest", arr, tempHeader);
		yield return www;
		
		if( www.error == null )
		{
			Debug.Log("Server says: "+ www.text);
			foreach(string key in www.responseHeaders.Keys)
			{
				Debug.Log(key + " - " + www.responseHeaders[key]);
				_requestHeader.Add(key, www.responseHeaders[key]);
			}
			_status = int.Parse(www.responseHeaders["STATUS"].ToString());
			_text = www.text;
			Debug.Log("Client closed.");
			isDone = true;
		}
		else
		{
			Debug.Log(www.text);
			Debug.Log(www.error);
			_error = www.error;
		}
	}	
*/
	
	void SendMultipartPacket()
	{
		isDone = false;
	
		string boundary = DateTime.Now.Ticks.ToString("x");

	
		client = new TcpClient(this.url, 80);
		Debug.Log("LC_WWW : SendMultipartPacket : Client connected.");
		
		NetworkStream networkStream = client.GetStream();
		
		System.Text.UTF8Encoding  encoding = new System.Text.UTF8Encoding();
		
		StringBuilder sb = new StringBuilder();

		foreach (string key in _parameter.Keys )
		{
			sb.Append("--"+boundary);
			sb.AppendLine();
			sb.Append("Content-disposition: form-data; name=\""+key+"\"");
			sb.AppendLine();
			sb.AppendLine();
			sb.Append(_parameter[key].ToString());
			sb.AppendLine();
		}
		
		sb.Append("--"+boundary);
		sb.AppendLine();
		sb.Append("Content-Type: image/png");
		sb.AppendLine();
		sb.Append("Content-disposition: form-data; name=\"photo\"; filename=\"screenShot.png\"");
		sb.AppendLine();
		sb.AppendLine();
		
		byte[] sbByte = encoding.GetBytes(sb.ToString());
		
		try
		{
//			HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://"+url+path);
//			httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
//		    httpWebRequest.Method = "POST";
//		    httpWebRequest.KeepAlive = true;
//			httpWebRequest.ContentLength = sbByte.Length;
//			
//			Debug.Log("headers : " + httpWebRequest.Headers.ToString());
//			Stream requestStream = httpWebRequest.GetRequestStream();
//			requestStream.Write(sbByte, 0, sbByte.Length);
//			requestStream.Close();
//			
//			WebResponse webResponse = httpWebRequest.GetResponse();
//			Stream responseStream = webResponse.GetResponseStream();
//			StreamReader reader = new StreamReader(responseStream);
//			
//			Debug.Log("sever says : " + reader.ReadToEnd());
//			webResponse.Close();
//			
//			Debug.Log("url : " + this.url);
//			Debug.Log("path : " + this.path);
			
			byte[] boundaryByte = Encoding.UTF8.GetBytes("\r\n--"+boundary+"--\r\n");
			byte[] messsage = Encoding.UTF8.GetBytes(method.ToString() + " " + this.path+" HTTP/1.1\r\n");
	        networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Host: "+ this.url +"\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Connection: keep-alive\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			messsage = Encoding.UTF8.GetBytes("Content-Type: multipart/form-data; boundary="+boundary+"\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
//			long len = memStream.Length + boundaryByte.Length;
			int len = sbByte.Length + _image.Length + boundaryByte.Length;
			messsage = Encoding.UTF8.GetBytes("Content-Length: " + len +"\r\n\r\n");
			networkStream.Write(messsage, 0, messsage.Length);
			
			networkStream.Write(sbByte, 0, sbByte.Length);   
			networkStream.Write(_image, 0, _image.Length);
			networkStream.Write(boundaryByte, 0, boundaryByte.Length);
			
			networkStream.Flush();
			
	        // Read message from the server.
	        string serverMessage = ReadMessage(networkStream);
	        Debug.Log("Server says: "+ serverMessage);
			
			_text = MakeHeader(serverMessage).Trim().Replace("\n","");
			
	        // Close the client connection.
	        client.Close();
	        
	        Debug.Log("Client closed.");
		}
		catch (Exception e){
			_error += e.Message;
			Debug.Log(e.Message);
		}
		
		isDone = true;
	}
	
	private string MakeHeader(string serverMessage){
		string header;
		while(true){
			if(serverMessage.IndexOf("\r\n") == 1){
				serverMessage = serverMessage.Substring(serverMessage.IndexOf("\r\n")+1);
				break;
			}
			header = serverMessage.Substring(0,serverMessage.IndexOf("\r\n")).Trim();
			serverMessage = serverMessage.Substring(serverMessage.IndexOf("\r\n")+1);
			if(header.Contains("HTTP/1.1")){			
				string[] temp = header.Split(" "[0]);
				int Status = int.Parse(temp[1]);
				
				_responseHeader.Add("status",Status);
				
				_status = Status;
			}
			else{
				if( !_responseHeader.Contains(header.Substring(0,header.IndexOf(":"))) )
					_responseHeader.Add(header.Substring(0,header.IndexOf(":")),header.Substring(header.IndexOf(":")+1).Trim());
			}
		}
	
		return serverMessage;
	}

	string ReadMessage(NetworkStream sslStream)
    {
        Debug.Log("LC_WWW : ReadMessage ");
		int byteSize = 2048;
        byte [] buffer = new byte[byteSize];
        StringBuilder messageData = new StringBuilder();
        int bytes = -1;
		int i=0;
		int contentlength = 0;
		int totalByte = 0;
		
		do
		{
			bytes = sslStream.Read(buffer, 0, buffer.Length);
            // Use Decoder class to convert from bytes to UTF8
            // in case a character spans two buffers.
            Decoder decoder = UTF8Encoding.UTF8.GetDecoder();
			char[] chars = new char[decoder.GetCharCount(buffer,0,bytes)];
			decoder.GetChars(buffer, 0, bytes, chars, 0);

			int offset = chars.Length - bytes;

			if( i == 0 )
			{
				messageData.Append(chars);
				int index = messageData.ToString().IndexOf("Content-Length: ")+16;
				int lastIndex = messageData.ToString().IndexOf("\r\n",index) - index;
				contentlength = int.Parse(messageData.ToString().Substring(index,lastIndex)) + offset;
				
				if(contentlength == 0){
					break;
				}
				
				if(messageData.ToString().Contains("\n[")){
					if(messageData.ToString().Substring(messageData.ToString().IndexOf("\n[")).Length == contentlength)
						break;
					totalByte += messageData.ToString().Substring(messageData.ToString().IndexOf("\n[")).Length;
				}
				else if(messageData.ToString().Contains("\n{")){
					if(messageData.ToString().Substring(messageData.ToString().IndexOf("\n{")).Length == contentlength)
						break;
					totalByte += messageData.ToString().Substring(messageData.ToString().IndexOf("\n{")).Length;
				} 
				i++;
			}
			else
			{
				messageData.Append(chars);
				totalByte += bytes;
			}
        } while(totalByte<contentlength);

        return messageData.ToString();
    }
}
